﻿using System.Net.DnsToolkit.Packet;
using System.Net.DnsToolkit.Serializer.Stream.Extension;
using System.Net.DnsToolkit.Util;
using System.Net.DnsToolkit.Packet.Busy;

namespace System.Net.DnsToolkit.Bastard.PacketGenerator {
    /// <summary>
    /// Creates DNS packet that has domain name compression pointer
    /// that point to itself, creating a loop.
    /// 
    /// Some explaination on the bug :
    /// ---------------------------------------------------------
    ///   Normal packet, compression disabled
    /// ---------------------------------------------------------
    /// 
    /// Message {
    ///     Header,
    ///     Questions {
    ///         Question0 {
    ///             Name = "question0.p"
    ///         }
    ///         Question1 {
    ///             Name = "question1.p"
    ///         }
    ///     }
    ///     Answers,
    ///     Authorities,
    ///     Additionals
    /// }
    /// 
    /// 
    /// ---------------------------------------------------------
    ///   Domain compression dual question loop
    /// ---------------------------------------------------------
    /// 
    /// Message {
    ///     Header,
    ///     Questions {
    ///         Question0 {
    ///             Name = "question0."+ pointer to Question1 offset 0 
    ///         }
    ///         Question1 {
    ///             Name = "question1."+ pointer to Question0 offset 0
    ///         }
    ///     }
    ///     Answers,
    ///     Authorities,
    ///     Additionals
    /// }
    /// 
    /// 
    /// 
    /// 
    /// </summary>
    public class DomainPointerDualLoop : IPacketGenerator {

        public byte[] GetBytes() {
            byte[] bs = GetMessage().GetBytes();
            bs[12]-- ;  // create some space for pointer
            bs[22] = CompressionConstant.NameCompression; // create pointer
            bs[23] = 28;                        // that forward to offset 29 (question1 offset 0)

            bs[28]-- ;  // create some space for pointer
            bs[38] = CompressionConstant.NameCompression; // create pointer
            bs[39] = 12;                        // that forward to offset 12 (question0 offset 0)
            
            return bs;
        }


        public IMessage GetMessage() {

            var message = new Message();
            message.Questions.AddRange(
                new Question[] {
                    new Question {
                        QName = new DomainName {
                            Name = "question0p"
                        },
                        QClass = QClassEnum.IN,
                        QType = QTypeEnum.A

                    },
                    new Question {
                        QName = new DomainName {
                            Name = "question1p"
                        },
                        QClass = QClassEnum.IN,
                        QType = QTypeEnum.A
                    }
                }
            );
            message.Header.QuestionCount = (ushort)message.Questions.Count;

            return message;
        }

    }
}
